package gpstools.track;

import gpstools.TrainingPoint;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Track implements Serializable {
    private static final long serialVersionUID = 1L;
    
    private final List<Lap> laps;
    private final TrackInfo info = new TrackInfo();

    private String name;

    public List<Lap> getLaps() {
        return Collections.unmodifiableList(laps);
    }

    public String getName() {
        return name;
    }

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {
        private List<Lap> laps = new ArrayList<Lap>();
        private Lap currentLap;
        private int counter = 0;
        private String name;

        public Builder() {
            createLap();
        }

        public Builder name(String name) {
            this.name = name;
            return this;
        }

        public Builder add(TrackPoint point) {
            if (point != null) {
                /* ignore null input */
                currentLap.add(point);
                counter++;
            }
            return this;
        }

        public Builder add(TrackPoint[] points) {
            if (points != null) {
                for (TrackPoint point : points) {
                    add(point);
                }
            }
            return this;
        }
        
        public Builder add(TrainingPoint point){
            return add(new TrackPoint(point));
        }

        public Builder add(TrainingPoint[] points) {
            if (points != null) {
                for (TrainingPoint point : points) {
                    add(point);
                }
            }
            return this;
        }
        
        public LapInfo closeLap() {
        	LapInfo info = currentLap.getInfo();
            if (!currentLap.isEmpty()) {
                /* skip empty laps */
                createLap();
            }
			return info;
        }

        private void createLap() {
            currentLap = new Lap();
            laps.add(currentLap);
        }

        public boolean isEmpty() {
            return counter == 0;
        }

        public Track build() {
            return new Track(this);
        }

    }

    public Track(Builder builder) {
        List<Lap> laps = new ArrayList<Lap>();
        for (Lap lap : builder.laps) {
            if (!lap.isEmpty()) {
                laps.add(lap);
            }
        }
        if (laps.isEmpty()) {
            throw new IllegalStateException("not enough data to create a track");
        }
        this.laps = laps;
        this.name = builder.name;
    }

    public List<TrackPoint> getPoints() {
        List<TrackPoint> points = new ArrayList<TrackPoint>();
        for (Lap lap : laps) {
            points.addAll(lap.getPoints());
        }
        return points;
    }
    
    public TrackInfo getInfo() {
        return info;
    }
}
